package demo.util;

import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * java 版本的数据库行锁,使用wait/notify实现，当然可以使用别的方式如Lock下的await/signal
 * 
 * @author hanjy
 *
 */
public class JavaRowLock<T> {

    private static Logger logger = LoggerFactory.getLogger(JavaRowLock.class);

    private ConcurrentHashMap<T, Object> lockedMap = new ConcurrentHashMap<>(256);

    private static final Object O = new Object();

    public static final Random R = new Random();

    public void lock(T id, int timeout) throws InterruptedException {
        long t1 = System.currentTimeMillis();
        while (lockedMap.putIfAbsent(id, O) != null) {
            safeSleep(1);
            logger.info("putIfAbsent {} failed,try again", id);
            if (System.currentTimeMillis() - t1 > timeout) {
                logger.info("putIfAbsent {} timeout", id);
                break;
            }
        }
        logger.info("putIfAbsent {} success", id);
    }

    public void unLock(T id) {
        Object o = lockedMap.remove(id);
        logger.info("remove {} return {}", id, o);
    }

    public static void safeSleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
    }
}
